#ifndef _INCLUDE_ONET_C_TCP_PORT
#define _INCLUDE_ONET_C_TCP_PORT_

/*!
    Copright: Kai "DrHalan" Mast - www.freakybytes.org

    This file is part of OpenNetwork. See OpenNetwork.h for license information.
*/


#include <OpenNetwork/INetworkPort.h>

#include "STCPPeer.h"

#include "extensions/BitStream/BitStream.h"

#include "STCPMessage.h"

#ifdef __WINDOWS__
#include <winsock2.h>
#include <Ws2tcpip.h>
#elif defined(__unix__)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <arpa/inet.h>
#else
#error "What's your operating system?"
#endif

#include <fcntl.h>

#include <memory.h>


#include "common.h"

namespace onet
{

    class CTCPPort : public INetworkPort
    {
    public:
        CTCPPort(INetworkCallback* callback_, u16 maxConnections_, u16 port_, bool listen_, bool IPv6_);

        ~CTCPPort();

        //! Initialization function
        virtual bool init(void);

        //! Connect to an address
        //! Returns false if already connected
        virtual bool connect(const SNetworkAddress& address);

        //! The disconnect pendant
        //! Returns false if the peerID is invalid
        virtual bool disconnect(const PeerID id);

        //! Disconnects all peers
        //! Returns number of peers disconnected
        virtual u16 disconnectAll(void);

        //! Gets the address (IP/Port) of a peer
        virtual SNetworkAddress getAddress(const PeerID id);

        //! Looks up if a certain address is connected
        virtual bool isConnected(const SNetworkAddress& a);

        //! Gets the Id of a certain address
        virtual PeerID getPeer(const SNetworkAddress& a);

        //! Sends and receives data
        virtual void work(void);

        //! Get the protocol used
        virtual EPortType getType(void) const;

        //! Get the latency of a peer
        virtual s32 getLatency(const PeerID id);

        //! Send data to peer - Reliable or not
        virtual bool send(const PeerID id, const u8 type, const u32 length, const c8* data, const bool reliable);

        //! Send data to address
        virtual bool sendRaw(const SNetworkAddress& address, const u16 length, const c8* data);

        //! Query certain features
        virtual bool hasFeature(EFeatureType type) const;

        //! Returns number of peers connected
        virtual u16 getPeerCount();

    private:
        //! Remove a peer (!= disconnect)
        void removePeer(PeerID id);

        //! Adds a peer (!= connect)
        void addPeer(PeerID id);

        //! Processes out messages
        void processSending();

        //! Processes in messages
        void processReceiving(PeerID id);

        //! Processes connecting
        void processConnecting(PeerID id);

        //! Process acccetping of new connectiong
        void processIncomingConnection();

        //! Pointer to the peer array
        PointerArray<STCPPeer> peers;

        //! We count the amount of peers connected
        u16 peerCount;

        //! The highest filedescriptor in the set
        s32 highest_fd;

        //! Socket used to send and receive data
        s32 listenfd;

        //! Buffer for receiving messages
        c8 buffer[1024];

        //! File Descriptor sets used by select()
        fd_set peer_fds;
        fd_set read_fds;
        fd_set write_fds;

        //! Vector holding all waiting messages
        std::vector<STCPMessage> messages;
    };

} //!end namespace onet

#endif
